package org.springframework.zp.aop.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.*;
import org.springframework.zp.aop.service.DeleteService;
import org.springframework.zp.aop.service.impl.DeleteBServiceImpl;

// @Component
// @Aspect
@Slf4j(topic = "e")
public class NotVeryUsefulAspect {

	/**
	 * 使用 DeclareParents 方式实现将 已有的代码新增方法，但可以避免修改已存在的类
	 * 简单理解就是让 接口A 的子类 A1 在不修改代码的情况下 具有 接口B 的指定方法，且该指定方法是子类 B1 实现的
	 * 即 代理后的代码可以理解为： UserServiceImpl implements UserService  implements DeleteService
	 */
	@DeclareParents(value = "org.springframework.zp.aop.service.impl.UserServiceImpl", defaultImpl = DeleteBServiceImpl.class)
	public static DeleteService deleteService;

	@Pointcut("execution(* org.springframework.zp.aop.service..*.*(..))")
	public void pointCutPackage() {

	}

	/**
	 * 针对指定方法做代理
	 */
	@Pointcut("execution(* org.springframework.zp.aop.service..*.method4(..))")
	public void pointCutPackageMethod() {

	}

	/**
	 * within 颗粒度只能精确到类
	 */
	@Pointcut("within(org.springframework.zp.aop.service.impl.ServiceImpl)")
	public void pointCutWithin() {

	}

	@Pointcut("within(org.springframework.zp.aop.service.impl.CglibTestService)")
	public void pointCutWithinCglibTestService() {

	}

	/**
	 * 针对参数做代理
	 */
	@Pointcut("args(Integer,String)")
	public void pointCutArgs() {

	}

	/**
	 * this 表示代理对象是 指定类型的，那么就针对里面所有的方法做代理,
	 */
	@Pointcut("this(org.springframework.zp.aop.service.Service)")
	public void pointCutThisInterface() {

	}

	/**
	 * this 表示代理对象是 指定类型的，那么就针对里面所有的方法做代理,由于该类存在接口，spring aop 会默认使用 jdk 代理，
	 * 那么此时的代理类就会是 $$Proxy,类已经变了，所以此时不会生效，如果想要生效的话，就需要 指定使用 cglib 方式来生成代理 ,即 @EnableAspectJAutoProxy(proxyTargetClass = true)
	 */
	@Pointcut("this(org.springframework.zp.aop.service.impl.ServiceImpl)")
	public void pointCutThis() {

	}

	/**
	 * target 到父类的话，效果和 this 一样
	 */
	@Pointcut("target(org.springframework.zp.aop.service.Service)")
	public void pointCutTarget() {

	}

	/**
	 * target 可以精确的表达出对具体的子类实现代理，这是和 this 的区别，不用考虑代理对象是 jdk 还是 cglib 代理情况
	 */
	@Pointcut("target(org.springframework.zp.aop.service.impl.ServiceImpl)")
	public void pointCutTargetImpl() {

	}

	/**
	 * 针对参数有指定注解的实现代理，即有且只有一个参数且参数上有指定注解才生效
	 */
	@Pointcut("@args(org.springframework.zp.aop.anno.Aop)")
	public void pointCutAnnoArgs() {

	}


	@Pointcut("@within(org.springframework.zp.aop.anno.Aop)")
	public void pointCutAnnoWithin() {

	}

	@Pointcut("@annotation(org.springframework.zp.aop.anno.Aop)")
	public void pointCutAnnoAnnotation() {

	}

	// 组合多个判断条件
	// @Before("pointCutPackageMethod() && pointCutAnnoArgs() ")

	@Before("pointCutAnnoAnnotation()")
	public void adviceBefore() {
		log.debug("******   before aop   ******");
	}


	//-------------------------------------------------------//

	@Pointcut("within(org.springframework.zp.aop.service.impl.AAopServiceImpl)")
	public void pointCutWithinAAopService() {

	}

	@Pointcut("within(org.springframework.zp.aop.service.impl.BAopServiceImpl)")
	public void pointCutWithinBAopService() {

	}

	@Before("pointCutWithinAAopService()")
	public void adviceBeforeAAopService() {
		log.debug("=======  before aop aservice  ========");

	}

	@After("pointCutWithinAAopService()")
	public void adviceAfterAAopService() {
		log.debug("=======after aop========");
	}

	@AfterReturning("pointCutWithinAAopService()")
	public void adviceAfterReturingAAopService() {
		log.debug("=======afterReturning aop========");
	}


	@Before("pointCutWithinBAopService()")
	public void adviceBeforeaBAopService() {
		log.debug("=======before aop bservice========");
	}
}
